package com.apartment.own.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.apartment.common.core.domain.model.LoginUser;
import com.apartment.common.exception.SubscribeException;
import com.apartment.common.utils.*;
import com.apartment.common.utils.date.DateRange;
import com.apartment.own.domain.*;
import com.apartment.own.domain.constant.ClassNameConstants;
import com.apartment.own.domain.enums.LeaseModeEnum;
import com.apartment.own.request.subscribe.OwnOrderSubscribeQuery;
import com.apartment.own.response.res.SubscribeResp;
import com.apartment.own.service.IOwnOrdCashPledgeService;
import com.apartment.own.service.IOwnOrdExtraChargeService;
import com.apartment.own.service.IOwnOrdTenantContractService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.DeleteBatchByIds;
import com.baomidou.mybatisplus.core.injector.methods.SelectList;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.apartment.own.mapper.OwnOrdSubscribeMapper;
import com.apartment.own.service.IOwnOrdSubscribeService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 添加预约 业务员记录租客的预约看房的记录Service业务层处理
 *
 * @author @Dog_E
 * @date 2020-08-28
 */
@Service
@Transactional
public class OwnOrdSubscribeServiceImpl extends ServiceImpl<OwnOrdSubscribeMapper, OwnOrdSubscribe> implements IOwnOrdSubscribeService {
    @Autowired
    private OwnOrdSubscribeMapper ownOrdSubscribeMapper;
    @Autowired
    private IOwnOrdTenantContractService iOwnOrdTenantContractService;
    @Autowired
    private IOwnOrdExtraChargeService iOwnOrdExtraChargeService;
    @Autowired
    private IOwnOrdCashPledgeService iOwnOrdCashPledgeService;
    /**
     * 查询添加预约 业务员记录租客的预约看房的记录
     *
     * @param id 添加预约 业务员记录租客的预约看房的记录ID
     * @return 添加预约 业务员记录租客的预约看房的记录
     */
    @Override
    public SubscribeResp selectOwnOrdSubscribeById(String id) {
        //查预约
        QueryWrapper<SubscribeResp> wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);
        SubscribeResp subscribeResp = ownOrdSubscribeMapper.selectOwnOrdSubscribeById(wrapper);
        //查预约押金
        QueryWrapper<OwnOrdCashPledge> wrapperCash = new QueryWrapper<>();
        wrapperCash.lambda()
                .eq(OwnOrdCashPledge::getForeignId,id);
        List<OwnOrdCashPledge> listCash = iOwnOrdCashPledgeService.list(wrapperCash);
        //查预约额外费用
        List<OwnOrdExtraCharge> listExtra = iOwnOrdExtraChargeService.list(new QueryWrapper<OwnOrdExtraCharge>().lambda().eq(OwnOrdExtraCharge::getForeignId, id));
        subscribeResp.setPledges(listCash!=null?listCash:null);
        subscribeResp.setExtraCharges(listExtra!=null?listExtra:null);
        return subscribeResp;
    }

    /**
     * 查询添加预约 业务员记录租客的预约看房的记录列表
     *
     * @param ownOrdSubscribe 添加预约 业务员记录租客的预约看房的记录
     * @return 添加预约 业务员记录租客的预约看房的记录
     */
    @Override
    public List<OwnOrdSubscribe> selectOwnOrdSubscribeList(OwnOrderSubscribeQuery ownOrdSubscribe) {
        List<OwnOrdSubscribe> list = list(
                new QueryWrapper<OwnOrdSubscribe>().lambda()
                        //----------------------------日期周期查询--------------------------------------------------
                        //起租日期范围查询
                        .between((ownOrdSubscribe.getTimeCycle() != null && ownOrdSubscribe.getTimeCycle() == 1), OwnOrdSubscribe::getStartLeaseTime, ownOrdSubscribe.getStartLeaseTimeStart(), ownOrdSubscribe.getStartLeaseTimeEnd())
                        //退租日期范围查询
                        .between((ownOrdSubscribe.getTimeCycle() != null && ownOrdSubscribe.getTimeCycle() == 2), OwnOrdSubscribe::getSurrenderLeaseTime, ownOrdSubscribe.getStartLeaseTimeStart(), ownOrdSubscribe.getStartLeaseTimeEnd())
                        //录入日期范围查询
                        .between((ownOrdSubscribe.getTimeCycle() != null && ownOrdSubscribe.getTimeCycle() == 3), OwnOrdSubscribe::getCreateTime, ownOrdSubscribe.getStartLeaseTimeStart(), ownOrdSubscribe.getStartLeaseTimeEnd())
                        //签约日期范围查询
                        .between((ownOrdSubscribe.getTimeCycle() != null && ownOrdSubscribe.getTimeCycle() == 4), OwnOrdSubscribe::getEstimatedSigningTime, ownOrdSubscribe.getStartLeaseTimeStart(), ownOrdSubscribe.getStartLeaseTimeEnd())
                        // --------------------------------·-end------------------------------------------------------
                        //录入人查询
                        .eq((ownOrdSubscribe.getClerk() != null), OwnOrdSubscribe::getCreateBy, ownOrdSubscribe.getClerk())
                        //预定方式查询
                        .eq((ownOrdSubscribe.getSubscribeType() != null), OwnOrdSubscribe::getSubscribeType, ownOrdSubscribe.getSubscribeType())
                        //出租类型查询
                        .eq((ownOrdSubscribe.getHousingType() != null), OwnOrdSubscribe::getHousingType, ownOrdSubscribe.getHousingType())
                        //------------------------- 手机号,房间号,姓名,小区综合查询----------------------------------------------------------
                        .and(ownOrdSubscribe.getManySearch() != null, x -> x
                                //小区
                                .or().like(OwnOrdSubscribe::getVillageName, ownOrdSubscribe.getManySearch())
                                //手机号
                                .or().like(OwnOrdSubscribe::getTel, ownOrdSubscribe.getManySearch())
                                //姓名
                                .or().like(OwnOrdSubscribe::getName, ownOrdSubscribe.getManySearch())
                                //房间号
                                .or().eq(OwnOrdSubscribe::getRoomId, ownOrdSubscribe.getManySearch())
                        )
                //----------------------------------------end--------------------------------------------------------------
        );
        return list;
    }


    /**
     * 新增添加预约 业务员记录租客的预约看房的记录
     *
     * @param ownOrdSubscribe 添加预约 业务员记录租客的预约看房的记录
     * @return 结果
     */
    @Override
    public int insertOwnOrdSubscribe(OwnOrderSubscribeQuery ownOrdSubscribe) {
        //判断是否有月租金
        if (null == ownOrdSubscribe.getRental()) {
            throw new SubscribeException(500, "月租金不能为空");
        }

        //判定身份证
        if (ownOrdSubscribe.getIdType() == 0 && !IDCardUtil.verify(ownOrdSubscribe.getIdNumber())) {
            throw new SubscribeException(500, "请输入正确的身份证");
        }
        //--------------------如果是个人用户--------------------------
        if (ownOrdSubscribe.getResidentType() == 0) {
            if (StringUtils.isBlank(ownOrdSubscribe.getName())) {
                throw new SubscribeException(500, "居住人姓名不能为空");
            }
        }
        //---------------------如果入住为企业--------------------------
        if (ownOrdSubscribe.getResidentType() == 1) {
            if (StringUtils.isBlank(ownOrdSubscribe.getEnterpriseContact())) {
                throw new SubscribeException(500, "企业联系人不能为空");
            }
            if (StringUtils.isBlank(ownOrdSubscribe.getBusinessLicense())) {
                throw new SubscribeException(500, "请核对营业执照");
            }
        }

        //获取登录用户
        LoginUser user = SecurityUtils.getLoginUser();
        ownOrdSubscribe.setCreateBy(user.getUsername());
        ownOrdSubscribe.setCreateTime(DateUtils.getNowDate());

        //查询房源在预约期是否有合同
        QueryWrapper<OwnOrdTenantContract> queryWrapper = new QueryWrapper<>();
        queryWrapper
                //搜索该房源在租约时间中是否有记录
                .eq("house_id", ownOrdSubscribe.getRoomId())
                .ge("start_lease_time", ownOrdSubscribe.getStartLeaseTime())
                .lt("surrender_lease_time", ownOrdSubscribe.getSurrenderLeaseTime());
        OwnOrdTenantContract contract = iOwnOrdTenantContractService.getOne(queryWrapper);
        if (contract != null) {
            throw new SubscribeException(500, "合同时间冲突，请重新选择！");
        }
        //查询房源在预约是否有其他预约
        QueryWrapper<OwnOrdSubscribe> queryWrappersub = new QueryWrapper<>();
        //搜索房源id
        queryWrappersub
                .eq("room_id", ownOrdSubscribe.getRoomId())
                //预约表中查询该房源在时间区间中是否有预约
                .eq("housing_type", ownOrdSubscribe.getHousingType())
                .ge("start_lease_time", ownOrdSubscribe.getStartLeaseTime())
                .lt("surrender_lease_time", ownOrdSubscribe.getSurrenderLeaseTime());
        OwnOrdSubscribe subscribe = ownOrdSubscribeMapper.selectOne(queryWrappersub);
        if (subscribe != null) {
            throw new SubscribeException(500, "预定时间冲突，请重新选择时间");
        }

        ownOrdSubscribe.setCreateTime(DateUtils.getNowDate());
        //添加预约
        save(ownOrdSubscribe);

        //添加预约--------------------押金------------------------
        List<OwnOrdCashPledge> ownOrdCashPledges = ownOrdSubscribe.getOwnOrdCashPledges();
        if (null != ownOrdCashPledges) {

            //判断押金类型,计算常规押金,判定常规押金输入是否正确
            System.out.println(estimateCashPledge(ownOrdSubscribe.getCashPledgeType(), ownOrdSubscribe.getRental(), ownOrdCashPledges.get(0).getCost()));
            if (ownOrdSubscribe.getCashPledgeType() != 1 && ownOrdSubscribe.getCashPledgeType() != 5) {
                if (!estimateCashPledge(ownOrdSubscribe.getCashPledgeType(), ownOrdSubscribe.getRental(), ownOrdCashPledges.get(0).getCost())) {
                    throw new SubscribeException(500, "押金输入异常");
                }
            }
            //如果类型为1,无押金
            if (ownOrdSubscribe.getCashPledgeType() == 1) {
                ownOrdCashPledges.get(0).setCost(new BigDecimal("0"));
            }
            ownOrdCashPledges.forEach(x -> {
                x.setCreateBy(user.getUsername());
                x.setCreateTime(DateUtils.getNowDate());
                x.setForeignId(ownOrdSubscribe.getId());
                x.setSurfaceName(ClassNameConstants.OWN_SUBSCRIBE_FK_CASH_PLEDGE);
            });
            //保存押金
            iOwnOrdCashPledgeService.saveBatch(ownOrdCashPledges);
        }

        //添加预约--------------------加收费用----------------------------
        List<OwnOrdExtraCharge> ownOrdExtraCharges = ownOrdSubscribe.getOwnOrdExtraCharges();
        if (null != ownOrdExtraCharges) {
            ownOrdExtraCharges.forEach(x -> {
                x.setCreateBy(user.getUsername());
                x.setCreateTime(DateUtils.getNowDate());
                x.setForeignId(ownOrdSubscribe.getId());
                x.setSurfaceName(ClassNameConstants.OWN_SUBSCRIBE_FK_EXTRA_CHARGE);
            });
            //保存加收费用
            iOwnOrdExtraChargeService.saveBatch(ownOrdExtraCharges);
        }

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        DateRange d = new DateRange(ownOrdSubscribe.getStartLeaseTime(), ownOrdSubscribe.getSurrenderLeaseTime());
        List<DateRange> list = d.splitByMonth();
        list.forEach(x -> System.out.println("start=" + df.format(x.getStart()) + ", end=" + df.format(x.getEnd())));


        return 1;
    }

    /**
     * 修改添加预约 业务员记录租客的预约看房的记录
     *
     * @param ownOrdSubscribe 添加预约 业务员记录租客的预约看房的记录
     * @return 结果
     */
    @Override
    public int updateOwnOrdSubscribe(OwnOrdSubscribe ownOrdSubscribe) {
        ownOrdSubscribe.setUpdateTime(DateUtils.getNowDate());
        return ownOrdSubscribeMapper.updateOwnOrdSubscribe(ownOrdSubscribe);
    }

    /**
     * 批量删除添加预约 业务员记录租客的预约看房的记录
     *
     * @param ids 需要删除的添加预约 业务员记录租客的预约看房的记录ID
     * @return 结果
     */
    @Override
    public int deleteOwnOrdSubscribeByIds(String[] ids) {
        List<String> collect = Arrays.stream(ids).collect(Collectors.toList());
        return ownOrdSubscribeMapper.deleteBatchIds(collect);
    }

    /**
     * 删除添加预约 业务员记录租客的预约看房的记录信息
     *
     * @param id 添加预约 业务员记录租客的预约看房的记录ID
     * @return 结果
     */
    @Override
    public int deleteOwnOrdSubscribeById(String id) {
        return ownOrdSubscribeMapper.deleteOwnOrdSubscribeById(id);
    }

    /**
     * 判断押金是否异常
     *
     * @param type       支付方式 如押1...
     * @param rental     租金
     * @param cashPledge 押金
     * @return
     */
    public boolean estimateCashPledge(Integer type, BigDecimal rental, BigDecimal cashPledge) {
        if (type >= 2 && type <= 4) {
            return rental.compareTo(cashPledge.divide(new BigDecimal(type - 1 + ""))) == 0;
        } else {
            return true;
        }
    }
}
